//
//  Animable.swift
//  ProtoParticle
//
//  Created by Rebouh Aymen on 13/03/2017.
//  Copyright © 2017 Aymen. All rights reserved.
//

import UIKit

protocol Animable {
    var icons: [UIImage] { get }
    var orientation: Double { get }
    var position: CGPoint { get }
    var shape: String { get }
    var size: CGSize { get }
    var renderMode: String { get }

    /// The color tint to apply to the contents
    var colors: [UIColor] { get }
    
    /// The number of emitted particles per second
    var birthRate: Float { get }
    
    /// It seems to be the speed at a given moment. So the bigger the value, the quicker the animation will be
    var velocity: CGFloat { get }
    
}

extension Animable {
    var shape: String {
        return kCAEmitterLayerLine
    }
    
    var colors: [UIColor] {
        return []
    }
    
    var position: CGPoint {
        return .zero
    }
    
    var renderMode: String {
        return kCAEmitterLayerUnordered
    }
}


extension Animable {
    
    func emitter() -> CAEmitterLayer {
        
        let emitter = CAEmitterLayer()
//CAEmitterLayer用于实现基于Core Animation的粒子发生器系统。
        
        emitter.emitterShape    = self.shape
/*emitterShape发射源的形状,也就是表示粒子从什么形状发射出来:
 kCAEmitterLayerPoint 点形状，发射源就是一个点，该点坐标为(emitterPosition.x, emitterPosition.y, emitterZPosition)
 kCAEmitterLayerLine 直线形状，发射源就是一条直线，从点(emitterPosition.x - emitterSize.width/2, emitterPosition.y, emitterZPosition) 到点 (emitterPosition.x + emitterSize.width/2, emitterPosition.y, emitterZPosition).
 kCAEmitterLayerRectangle 矩形形状，发射源就是一个矩形，[emitterPosition.x - emitterSize.width/2, emitterPosition.y - emitterSize.height/2, emitterZPosition], [emitterPosition.x + emitterSize.width/2, emitterPosition.y + emitterSize.height/2, emitterZPosition]
kCAEmitterLayerCuboid 立体矩形形状(3D)，发射源是一个立体矩形，需要设置z方向的数据，如果不设置，如同rectangle，[emitterPosition.x - emitterSize.width/2, emitterPosition.y - emitterSize.height/2, emitterZPosition - emitterDepth/2], [emitterPosition.x + emitterSize.width/2, emitterPosition.y + emitterSize.height/2, emitterZPosition+emitterDepth/2].
 kCAEmitterLayerCircle 圆形，发射源是一个圆形，圆心(emitterPosition.x, emitterPosition.y, emitterZPosition) ，半径emitterSize.width.
 kCAEmitterLayerSphere 3D球
 
其中立体矩形和3D球形需要用到：
 emitterZPosition CGFloat  为发射源中心沿z轴的距离。
 emitterDepth CGFloat    发射源形状的深度。
 */
        emitter.emitterPosition = self.position
//emitterPosition决定了粒子发射形状的中心点
        
        emitter.emitterSize     = self.size
//emitterSize发射源的尺寸大小, 与emitterShape结合，可以确定发射源的坐标范围
        
        emitter.renderMode      = self.renderMode
//renderMode渲染模式, 默认kCAEmitterLayerUnordered,
/*
 kCAEmitterLayerUnordered 粒子是无序出现的，多个发射源将混合。
 kCAEmitterLayerOldestFirst  生命久的粒子会被渲染在最上层。
 kCAEmitterLayerOldestLast 刚开始的粒子会被渲染在最上层。
 kCAEmitterLayerBackToFront 刚开始的粒子会被渲染在最上层
 kCAEmitterLayerAdditive 这种模式会进行粒子混合
 */
        
//        emitter.emitterMode = kCAEmitterLayerLine
/*
 emitterMode即发射模式，进一步决定发射的区域是在发射源形状的哪一部分。默认是volume
 points：粒子从粒子发射源上的点发射出来。
 outline：粒子从粒子发射源的轮廓发射。
 surface：粒子从粒子发射源的表面发射出去。
 volume：粒子从粒子发射源内的某个位置发射出来。
 */
//        emitter.birthRate = self.birthRate*0.1
//粒子出生率系数，默认为1.0。每个粒子cell的birthRate乘以这个系数得到每秒生产粒子的个数，即每秒生产粒子数=Layer.birthRath * Cell.birthRate.
        
        emitter.emitterCells    = nil //self.icons.map { emitterCell(withImage: $0) }
//emitterCells  [CAEmitterCell]?  添加到粒子图层中的粒子cell数组，可以控制粒子的种类个数
        
        
        if self.colors.isEmpty {
            emitter.emitterCells  = self.icons.map { emitterCell(withImage: $0) }
        } else {
            emitter.emitterCells  = self.colors.enumerated().map { emitterCell(withImage: self.icons.first!, usingColor: $0.element) }
        }

        return emitter
    }
    
    func emitterCell(withImage image: UIImage, usingColor color: UIColor? = nil) -> CAEmitterCell {
        
        let emitterCell = CAEmitterCell()
//粒子cell
        emitterCell.birthRate         = self.birthRate
//每秒产生粒子对象的数量
        
        emitterCell.lifetime          = 7
//粒子cell的生命周期，以秒计算。
//假如，Cell的lifetime（生命周期）为1，其所属CAEmitterLayer的lifetime为2时，
//在其它参数选择默认值的情况下，这个CAEmitterCell的生命周期就是1*2=2秒，2秒后，CAEmitterCell就会从粒子系统中被移除。
        emitterCell.lifetimeRange = 3
// 粒子cell的生命周期变化范围。比如lifetime为10秒，lifttimeRange是3秒，那么cell的实际生命周期范围是7(10-3)到13(10+3)秒。
        
        emitterCell.velocity          = self.velocity // the bigger the value is, the quicker the fruit move
//粒子cell的初始速度 （cell.velocity 乘以 layer.velocity）等于粒子的速度
        emitterCell.velocityRange = 20
//粒子cell的速度变化范围 velocity-velocityRange to velocity+velocityRange
        
        emitterCell.emissionLongitude = CGFloat(self.orientation)
//发射角的经度方向。经度角代表了在x-y轴平面坐标系中与x轴之间的夹角，也就是粒子在xy平面的发射角度，默认0，切记在iOS上0度角表示Y轴向上的方向，（并不是x轴向右飞行。）
//顺时针方向是正向，所以如果想沿着y轴向下飞行，那么在iOS中需设置为PI即即180度，如果粒子沿着x轴向左飞行，则可设置为 3*PI/2也可设置为 -PI/2。
//而emissionLatitude指定了纬度, 纬度角代表了x-z轴平面上与x轴之间的夹角，两者默认0:
        
        emitterCell.emissionRange     = CGFloat(M_2_PI)//M_1_PI=1/pi，而π等于180弧度，所以M_1_PI=1/180弧度 = 2/360 = 2°
//发射粒子角度范围，默认0，以锥形分布开的发射角度。角度用弧度制。粒子均匀分布在这个锥形范围内。
//比如emissionLongitude=M_PI，则发射角度Y轴笔直向下，再叠加emissionRange=M_2_PI，则会向Y轴偏左下4度和Y轴偏右4度范围内发射
        
        emitterCell.contents          = image.cgImage
//显示内容。
        
        emitterCell.scale = 0.7
//粒子缩放比例系数，默认为1.0
        emitterCell.scaleRange = 0.3
//单元大小改变的范围，即实际的放缩为scale-scaleRange~scale+scaleRange不等
//这个range 和 speed 决定了在单元存活时间里，它的大小变化的范围和速度
        emitterCell.scaleSpeed  = -0.1 // The bigger the value is, the quicker the fruit size grow
//粒子cell的生命周期内，scale每秒的变化速率，默认值0.0; 为正数表示scale由小大到，为负数表示由大到小变化
//        emitterCell.alphaSpeed = -1
//        alpha成分在细胞生命周期内的变化速度(以秒为单位),为负数表从不透明到透明
        if let color = color {
            emitterCell.color = color.cgColor
//粒子的颜色，默认为不透明的白色。
        }

        emitterCell.spin = 0.2
//粒子自旋系数，默认为1.0。计算方式同
        
        return emitterCell
    }
}
